package com.lz.comm.widget

import android.content.Context
import android.util.AttributeSet
import android.view.ViewGroup
import com.lz.comm.R

class GridLayout : ViewGroup {
    /**
     * 垂直间距
     */
    private var verticalSpace = 0

    /**
     * 水平间距
     */
    private var horizontalSpace = 0

    /**
     * 列数
     */
    private var numColumns = 1

    /**
     * 控件测试结果宽高
     */
    private var mWidth = 0

    /**
     * 控件测试结果宽高
     */
    private var mHeight = 0

    /**
     * 子控件宽度
     */
    private var childWidth = 0

    /**
     * 每一层控件的高度
     */
    private var childHeights = ArrayList<Int>()

    /**
     * 总行数
     */
    private var lines = 0

    /**
     * 添加子控件的布局参数
     */
    private var childParams: LayoutParams? = null

    constructor(context: Context) : super(context) {
        init(context, null)
    }

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        init(context, attrs)
    }

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        init(context, attrs)
    }

    private fun init(context: Context, attrs: AttributeSet?) {
        if (attrs != null) {
            val a = context.obtainStyledAttributes(attrs, R.styleable.GridLayout)
            numColumns = a.getInt(R.styleable.GridLayout_numColumns, numColumns)
            horizontalSpace =
                a.getDimensionPixelOffset(R.styleable.GridLayout_horizontalSpace, horizontalSpace)
            verticalSpace =
                a.getDimensionPixelOffset(R.styleable.GridLayout_verticalSpace, verticalSpace)
            a.recycle()
        }
        childParams = LayoutParams(0, LayoutParams.WRAP_CONTENT)
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        mWidth = MeasureSpec.getSize(widthMeasureSpec)
        val childMeasureWidths =
            mWidth - paddingLeft - paddingRight - (numColumns - 1) * horizontalSpace
        childWidth = childMeasureWidths / numColumns
        childParams!!.width = childWidth
        if (childCount <= 0) {
            setMeasuredDimension(paddingLeft + paddingRight, paddingTop + paddingBottom)
            return
        }
        lines = computeLines(childCount)
        childHeights.clear()
        for (i in 0 until lines) {
            childHeights.add(0)
        }
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            if (child.visibility == GONE) continue
            child.layoutParams.width = childWidth
            measureChild(child, widthMeasureSpec, heightMeasureSpec)
            val currentLine = getLine(i)
            val currentHeight: Int = child.measuredHeight
            if (currentHeight > childHeights[currentLine]) { //取当前行最高的值
                childHeights[currentLine] = currentHeight
            }
        }
        mHeight = computeHeight()
        setMeasuredDimension(mWidth, mHeight)
    }

    /**
     * 计算行数
     */
    private fun computeLines(count: Int): Int {
        var line = count / numColumns
        val last = count % numColumns
        if (last > 0) line++
        return line
    }

    /**
     * 根据position获取所在的行位置
     */
    private fun getLine(position: Int): Int {
        return position / numColumns
    }

    /**
     * 计算控件高度
     */
    private fun computeHeight(): Int {
        var height = paddingTop + paddingBottom
        for (i in 0 until childHeights.size) {
            height += childHeights[i] + verticalSpace
        }
        height -= verticalSpace
        return height
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        var left = paddingLeft
        var top = paddingTop
        for (i in 0 until lines) {
            val currentLineHeight = childHeights[i]
            for (j in 0 until numColumns) {
                val position = i * numColumns + j
                if (position >= childCount) return
                val child = getChildAt(position)
                if (child.visibility == GONE) continue
                child.layout(left, top, left + childWidth, top + currentLineHeight)
                left += childWidth + horizontalSpace
            }
            top += currentLineHeight + verticalSpace
            left = paddingLeft
        }
    }
}